package com.robcity.platform.util;

/**
 * @Description
 * @Author zhangsong
 * @Date 2024/9/5
 **/
public class GeoFenceChecker {

    // 地球半径（单位：米）
    private static final double EARTH_RADIUS = 6371000.0;

    /**
     * 将角度转换为弧度
     * @param degree 输入的角度
     * @return 返回对应的弧度值
     */
    private static double toRadians(double degree) {
        return degree * Math.PI / 180;
    }

    /**
     * 使用 Haversine 公式计算两个经纬度点之间的距离
     * @param lon1 第一个点的经度
     * @param lat1 第一个点的纬度
     * @param lon2 第二个点的经度
     * @param lat2 第二个点的纬度
     * @return 返回两个点之间的距离（单位：米）
     */
    public static double haversineDistance(double lon1, double lat1, double lon2, double lat2) {
        // 将纬度和经度从度转换为弧度
        double lat1Rad = toRadians(lat1); // 第一个点的纬度转换为弧度
        double lat2Rad = toRadians(lat2); // 第二个点的纬度转换为弧度
        double deltaLat = toRadians(lat2 - lat1); // 两个纬度的差值，转换为弧度
        double deltaLon = toRadians(lon2 - lon1); // 两个经度的差值，转换为弧度

        // Haversine 公式的计算
        double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
                Math.cos(lat1Rad) * Math.cos(lat2Rad) *
                        Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 计算并返回距离，单位为米
        return EARTH_RADIUS * c;
    }

    /**
     * 检查某个点是否在以指定半径为范围的区域内
     * @param centerLon 中心点的经度
     * @param centerLat 中心点的纬度
     * @param targetLon 目标点的经度
     * @param targetLat 目标点的纬度
     * @param radius 该区域的半径（单位：米）
     * @return 如果目标点在半径范围内，返回true；否则返回false
     */
    public static boolean isPointInRadius(double centerLon, double centerLat, double targetLon, double targetLat, double radius) {
        // 计算中心点与目标点之间的距离
        double distance = haversineDistance(centerLon, centerLat, targetLon, targetLat);

        // 判断距离是否小于或等于给定的半径
        return distance <= radius;
    }

    public static void main(String[] args) {
        // 中心点的经纬度（例如：上海）
        double centerLon = 121.4737; // 经度
        double centerLat = 31.2304; // 纬度

        // 目标点的经纬度
        double targetLon = 121.4800; // 经度
        double targetLat = 31.2400; // 纬度

        // 半径，单位为米
        double radius = 5000.0; // 半径为5000米

        // 判断目标点是否在半径范围内
        boolean isInRadius = isPointInRadius(centerLon, centerLat, targetLon, targetLat, radius);

        if (isInRadius) {
            System.out.println("目标点在范围内");
        } else {
            System.out.println("目标点不在范围内");
        }
    }
}
